package com.edu.advice;

import cn.hutool.core.bean.BeanUtil;
import com.edu.annotation.EnableLimitPage;
import com.edu.annotation.EnableRedisCache;
import com.edu.myenum.TypeMethod;
import com.edu.util.JsonUtil;
import com.edu.util.RedisClientUtil;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 这个类用来拦截我写的自定义注解
 *
 * @作者 five-five
 * @创建时间 2021/1/12
 */
@Component
@Aspect
public class RedisCacheAdvice {
    @Autowired
    private RedisClientUtil redisClientUtil;

    @Around(value = "@annotation(com.edu.annotation.EnableRedisCache)")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) {
        Object proceed =null;
        //获取方法签名
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        try {
            //获取EnableRedisCache注解
            Method proxyMethod = signature.getMethod();
            //根据方法名和方法参数类型去查找方法
            Method targetMethod = proceedingJoinPoint.getTarget().getClass().getMethod(proxyMethod.getName(), proxyMethod.getParameterTypes());
            EnableRedisCache enableRedisCache = targetMethod.getAnnotation(EnableRedisCache.class);
            //如果获取了这个注解，那么就不进redis缓存
            EnableLimitPage annotation = targetMethod.getAnnotation(EnableLimitPage.class);
            if (annotation != null) {
                //直接放行，不去缓存
                return proceedingJoinPoint.proceed();
            }
            String rediskey = enableRedisCache.value();
            TypeMethod type = enableRedisCache.type();
            //执行方法，并取得返回值，注意尽管控制台对某一对象没有打印出他的toString(),但是有指向的话那就没关系
//            Object invoke = targetMethod.invoke(proceedingJoinPoint.getTarget(), proceedingJoinPoint.getArgs());
            proceed = proceedingJoinPoint.proceed();//这个也是执行方法。。
            if (type == TypeMethod.SELECT) {
                //查询
                synchronized (rediskey) {
                    if (StringUtils.isNotBlank(rediskey) && BeanUtil.isNotEmpty(proceed)) {
                        String value = JsonUtil.objectToJson(proceed);
                        redisClientUtil.set(rediskey, value);
                    }
                }
            }else {
                synchronized (rediskey) {
                    //开始进行删除键
                    redisClientUtil.del(rediskey);
                }
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return proceed;
    }
}
